package email.core;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;

import email.util.XMLResourceBundleControl;

/**
 * Application configuration loader
 * 
 * @author dmatyukhin
 * 
 */
public class ConfigurationProvider {
	final static Logger LOGGER = Logger.getLogger(ConfigurationProvider.class
			.getName());
	private List<Mailbox> mailboxes;
	private ResourceBundle messages;
	private String configurationLocation = "mailboxmonitor";
	private String messagesLocation = "messages";

	public String getMessageString(String key) {
		return this.getMessageString(key, key);
	}

	public String getMessageString(String key, String defaultValue) {
		String result = defaultValue;
		if (messages == null) {
			try {
				messages = ResourceBundle.getBundle(messagesLocation, Locale.getDefault(), new XMLResourceBundleControl());
			} catch (MissingResourceException e) {
				LOGGER.log(Level.SEVERE, "Resource bundle file messages[_locale].properties not found!");
			}
		}
		if (messages != null) {
			try {
				result = messages.getString(key);
			} catch (MissingResourceException e) {
				LOGGER.log(Level.SEVERE, "Resource key=[" + key + "] is not found in the bundle");
			}

		}
		return result;
	}

	public List<Mailbox> getMailboxList() {
		if (this.mailboxes == null) {
			this.mailboxes = new ArrayList<Mailbox>();
			try {
				ResourceBundle p = ResourceBundle.getBundle(configurationLocation, Locale.getDefault(), new XMLResourceBundleControl());
				String countString = p.getString("mailbox.indexes");
				if (countString != null) {
					String[] mailboxIndexes = countString.split(",");
					for (String mailboxIndex : mailboxIndexes) {
						if (mailboxIndex == null || "".equals(mailboxIndex.trim())) {
							continue;
						}
						String alias = getResourceString(p, "mailbox." + mailboxIndex + ".alias", "Mailbox " + mailboxIndex);
						String poll = getResourceString(p, "mailbox." + mailboxIndex + ".poll", "10");
						String host = getResourceString(p, "mailbox." + mailboxIndex + ".host", null);
						String port = getResourceString(p, "mailbox." + mailboxIndex+ ".port", null);
						String protocol = getResourceString(p, "mailbox." + mailboxIndex + ".protocol", null);
						String user = getResourceString(p, "mailbox." + mailboxIndex + ".user", null);
						String pass = getResourceString(p, "mailbox." + mailboxIndex + ".pass", null);
						String retrHeaders = getResourceString(p, "mailbox." + mailboxIndex + ".retrheaders", null);
						// TODO: better data validation
						if (host == null || user == null || pass == null || protocol == null) {
							continue;
						}
						Mailbox m = new Mailbox();
						m.alias = alias;
						m.poll = Integer.parseInt(poll);
						m.host = host;
						if (port != null) { m.port = Integer.parseInt(port); }
						m.protocol = EmailChecker.Protocol.valueOf(protocol).name();
						m.user = user;
						m.pass = pass;
						m.useRetrHeaders = Boolean.valueOf(retrHeaders);
						mailboxes.add(m);
					}
				}
			} catch (NullPointerException e) {
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (MissingResourceException e) {
				e.printStackTrace();
			}
		}
		return this.mailboxes;
	}

	String getResourceString(ResourceBundle bundle, String key, String defaultValue) {
		String result = defaultValue;
		try {
			result = bundle.getString(key);
		} catch (NullPointerException e) {
			LOGGER.log(Level.SEVERE, "String property for null key cannot be retrieved", e);
		} catch (MissingResourceException e) {
			LOGGER.log(Level.WARNING, "Property for key=["+key+"] not found in the resource bundle", e);
		} catch (ClassCastException e) {
			LOGGER.log(Level.WARNING, "Property of type String for key=["+key+"] not found in the resource bundle", e);
		}
		return result;
	}
	
	private final static ConfigurationProvider INSTANCE = new ConfigurationProvider();

	public static ConfigurationProvider getInstance() {
		return INSTANCE;
	}

	public void setConfigurationLocation(String configLocation) {
		this.configurationLocation = configLocation;
	}

	public void setMessagesLocation(String messagesLocation) {
		this.messagesLocation = messagesLocation;
	}

}